#include "Ext_StrPrint.h"

/********************  串口打印  ************************/
static char *myitoa(uint32_t value, char *string, uint32_t radix)
{
    char *ptr = string;
    uint32_t i = 0, d = 0;

    switch (radix)
    {
    case 10:
        // 值 是负数|零退出
        if (value <= 0)
        {
            ptr[0] = '0';
            ptr[1] = 0;

            return string;
        }

        while (value)
        {
            d = value % 10;

            ptr[i ++] = (char)(d + '0');
            
            value /= 10;
        }

        /* 结束字符串 */
        ptr[i--] = 0;
        break;
    
    case 16:
        do
        {
            d = value & 0x0F;

            if (d < 10)
            {
                ptr[i] = (char)(d + '0');
            }
            else
            {
                ptr[i] = (char)(d + 55);
            }
            i ++;
            
            value >>= 4;
            
        } while (value);

        // 偶数位
        if (i & 0x01)
        {
            ptr[i++] = '0';
        }
        
        /* 结束字符串 */
        ptr[i--] = 0;
        break;
    
    default:
        /* 不支持的进制转换 */
        *ptr = 0;
        return string;
    }

    // 整理字符串
    #if 1
        while (ptr < &string[i])
        {
            d = *ptr;
            *ptr ++   = string[i];
            string[i] = (char)d;

            i --;
        }
    #else // 有趣的方法
        while (ptr < &string[i])
        {
            *ptr      ^= string[i];
            string[i] ^= *ptr;
            *ptr      ^= string[i];

            ptr ++;
            i --;
        }
    #endif

    return string;
}

uint8_t String_format(char *DestStr, const char *Str, va_list ap)
{
    char buf[16] = {0};
    const char *s;
    uint32_t d = 0;
    uint8_t StrLen = 0; 

    while (*Str != 0)  // 判断是否到达字符串结束符
    {
        if (*Str == 0x5C) //'\'
        {
            Str++;

            switch (*Str)
            {
            case 'r': //回车符
                DestStr[StrLen] = 0x0D;
                break;

            case 'n': //换行符
                DestStr[StrLen] = 0x0A;
                break;

            default:
                break;
            }

            StrLen ++;
        }
        else if (*Str == '%')
        {
            Str++;

            switch (*Str)
            {
            case 's': { //字符串
                s = va_arg(ap, const char *);

                for (; *s; s++)
                {
                    DestStr[StrLen ++] = *s;
                }
                break;
            }

            case 'u':   //无符号
            case 'd': { //十进制
                d = va_arg(ap, int);

                myitoa(d, buf, 10);

                for (s = buf; *s; s++)
                {
                    DestStr[StrLen ++] = *s;
                }
                break;
            }

            case 'x':
            case 'X': { //十六进制
                d = va_arg(ap, int);

                myitoa(d, buf, 16);

                for (s = buf; *s; s++)
                {
                    DestStr[StrLen ++] = *s;
                }
                break;
            }

            default:
                break;
            }
        }
        else
        {
            DestStr[StrLen ++] = *Str;
        }
        
        Str ++;
    }

    return StrLen;
}

uint8_t String_Printf(char *DestStr, const char *Str, ...)
{
    uint8_t DataLen = 0;

    va_list ap;
    va_start(ap, Str);
    
    DataLen = String_format(DestStr, Str, ap);

    va_end(ap);

    return DataLen;
}
